home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The World of Computer Software
/
The World of Computer Software.iso
/
oobpls10.zip
/
GIFVIDEO.PAS
< prev
next >
Wrap
Pascal/Delphi Source File
|
1992-11-06
|
54KB
|
2,234 lines
{$A+,F+,R-,S-,T-,V-,X+}
{***********************************************}
{* GIFVIDEO.PAS 1.0d *}
{* Copyright (c) Steve Sneed 1991 *}
{* All Rights Reserved *}
{* *}
{* Provided to TurboPower Software for their *}
{* use or distribution with their products *}
{***********************************************}
{$IFNDEF Ver60}
{$IFNDEF Ver70}
!! FATAL: This unit requires TP6 or later !!
{$ENDIF}
{$ENDIF}
unit GIFVideo; {basic video routines for example GIF decoder}
{The following define controls whether SVGA capabilities are supported. If
you don't have an SVGA card, undefining this conditional will save you some
code and data space.}
{$DEFINE UseSVGA}
interface
uses
DOS,
Dpmi,
OpString,
OpCrt,
DeGIF;
const
UnitVers = '1.0d';
UnitDate = '05-Jun-91';
const
DoDbl : Boolean = True;
Use50Line : Boolean = False;
const
VGASele : Word = $A000;
VidBIOSSele : Word = $C000;
OldMode : Word = 3; {our starting text mode}
OldFont8x8 : Boolean = False; {TRUE if in 8x8 font mode}
GraphOn : Boolean = False; {TRUE when we are in a graphics vid mode}
SVGAType : Integer = 0; {our type number for the SVGA chipset}
VidChecked : Boolean = False; {TRUE after SVGAType checked at least once}
VESAAvail : Boolean = False; {TRUE if a VESA driver is found}
ViaBIOS : Boolean = False; {TRUE to use the BIOS for bankswitching}
AllowEGAMode12 : Boolean = True; {set FALSE if your EGA can't do Mode $12}
m360x480x256 = $F0; {special VGA "Mode X" identifier}
{$IFDEF UseSVGA}
const
{consts for popular SVGA chipsets}
vtEGAVGA = 0;
vtCirrus = 1;
vtEverex = 2;
vtAcuMOS = 3;
vtParadise = 4;
vtTrident8800 = 5;
vtTrident8900 = 6;
vtTseng3000 = 7;
vtTseng4000 = 8;
vtAtiVGA = 9;
vtAheadA = 10;
vtAheadB = 11;
vtOakTech = 12;
vtVideo7 = 13;
vtChipsTech = 14;
vtGenoa = 15;
vtNCR = 16;
vtCompaq = 17;
vtS3VGA = 18;
vtVESA = 19;
(* NOTE: Those types marked with {*} _require_ a VESA driver to be in use! *)
SVGANames : Array[vtEGAVGA..vtVESA] of String[12] =
('Standard VGA',
'Cirrus', {*}
'Everex',
'AcuMOS',
'Paradise',
'Trident 8800',
'Trident 8900',
'Tseng 3000',
'Tseng 4000',
'VGA Wonder',
'Ahead "A"',
'Ahead "B"',
'Oak Tech.',
'Video 7',
'C & T',
'Genoa',
'NCR',
'Compaq', {*}
'S3 SVGA', {*}
'VESA driver');
{internal consts for "typical" SVGA modes we support. These numbers were}
{chosen because they do not conflict with any known BIOS mode numbers.}
m640x400x256 = $F1;
m640x480x256 = $F2;
m800x600x16 = $F3;
m800x600x256 = $F4;
m1024x768x16 = $F5;
m1024x768x256 = $F6;
m1024x768x32768 = $F7;
m1280x1024x16 = $F8;
m1280x1024x256 = $F9;
m1280x1024x32768 = $FA;
{$ENDIF}
type
PlotLineProc = procedure(Y : Word); {proc ptr type for PlotLine to use}
{$IFDEF UseSVGA}
type
{Our mode table record types}
ModeRecord =
record
Index : Byte;
ModeAX : Word;
ModeBL : Byte;
MaxC : Word;
end;
ModeTable = Array[1..6] of ModeRecord;
type
s80 = string[80];
s8 = string[8];
{types used in the VESA main records}
ByteString = Array[0..3] of Byte;
CharString = array[0..3] of Char;
CharStringPtr = ^CharString;
{pointer to a null-terminated list of words defining *all* modes the}
{card supports, including text and non-VESA graphics modes. The}
{VESA mode numbers will typically be the last ones in the list.}
ModeListType = array[0..0] of Word;
ModeListPtr = ^ModeListType;
var
VGAMem : Word;
BkSize : Word;
CurBk : Word;
type
{Record for basic VESA support info (VESA service $00)}
VgaInfoBlockType =
record
VESASignature : CharString;
VESAVersion : word;
OEMStringPtr : CharStringPtr;
Capabilities : ByteString;
VideoModePtr : ModeListPtr;
reserved : array[$00..$ED] of Byte; {Pad to 256}
end;
{pointer to a procedure that performs special memory paging. This}
{proc may exist within the hardware BIOS or in the VESA driver, or}
{it may be null and be used for other things.}
PageFuncPtrType = Pointer;
{Record containing information on a specific video mode. IMPORTANT:}
{the card *must be in the requested mode* when VESA service $03 is}
{called for this structure to be guaranteed to contain meaningful}
{information!}
ModeInfoBlockType =
record
{mandatory information}
ModeAttributes : word;
WinAAttributes : byte;
WinBAttributes : byte;
WinGranularity : word;
WinSize : word;
WinASegment : word;
WinBSegment : word;
WinFuncPtr : PageFuncPtrType;
BytesPerScanLine : word;
{optional information}
XResolution : word;
YResolution : word;
XCharSize : byte;
YCharSize : byte;
NumberOfPlanes : byte;
BitsPerPixel : byte;
NumberOfBanks : byte;
MemoryModel : byte;
BankSize : byte;
reserved : array[$00..$E2] of Byte; {Pad to 256}
end;
{ NOTE: The following tables assume at least 512k video memory is on the }
{ supported card, with 1Mb on those that can handle it (Tseng 4000 and }
{ Trident 8900, Ahead B/5000, etc.) }
const
Tseng3000Table : ModeTable =
((Index : m640x400x256; ModeAX : $002d; ModeBL : $00; MaxC : 256),
(Index : m640x480x256; ModeAX : $002e; ModeBL : $00; MaxC : 256),
(Index : m800x600x16; ModeAX : $0029; ModeBL : $00; MaxC : 16),
(Index : m800x600x256; ModeAX : $0030; ModeBL : $00; MaxC : 256),
(Index : m1024x768x16; ModeAX : $0037; ModeBL : $00; MaxC : 16),
(Index : 0; ModeAX : $0000; ModeBL : $00; MaxC : 0));
Tseng4000Table : ModeTable =
((Index : m640x400x256; ModeAX : $002f; ModeBL : $00; MaxC : 256),
(Index : m640x480x256; ModeAX : $002e; ModeBL : $00; MaxC : 256),
(Index : m800x600x16; ModeAX : $0029; ModeBL : $00; MaxC : 16),
(Index : m800x600x256; ModeAX : $0030; ModeBL : $00; MaxC : 256),
(Index : m1024x768x16; ModeAX : $0037; ModeBL : $00; MaxC : 16),
(Index : m1024x768x256; ModeAX : $0038; ModeBL : $00; MaxC : 256));
TridentTable : ModeTable =
((Index : m640x400x256; ModeAX : $005c; ModeBL : $00; MaxC : 256),
(Index : m640x480x256; ModeAX : $005d; ModeBL : $00; MaxC : 256),
(Index : m800x600x16; ModeAX : $005b; ModeBL : $00; MaxC : 16),
(Index : m800x600x256; ModeAX : $005e; ModeBL : $00; MaxC : 256),
(Index : m1024x768x16; ModeAX : $005f; ModeBL : $00; MaxC : 16),
(Index : 0; ModeAX : $0000; ModeBL : $00; MaxC : 0));
Trident8900Table : ModeTable =
((Index : m640x400x256; ModeAX : $005c; ModeBL : $00; MaxC : 256),
(Index : m640x480x256; ModeAX : $005d; ModeBL : $00; MaxC : 256),
(Index : m800x600x16; ModeAX : $005b; ModeBL : $00; MaxC : 16),
(Index : m800x600x256; ModeAX : $005e; ModeBL : $00; MaxC : 256),
(Index : m1024x768x16; ModeAX : $005f; ModeBL : $00; MaxC : 16),
(Index : m1024x768x256; ModeAX : $0062; ModeBL : $00; MaxC : 256));
AheadTable : ModeTable =
((Index : m640x400x256; ModeAX : $0060; ModeBL : $00; MaxC : 256),
(Index : m640x480x256; ModeAX : $0061; ModeBL : $00; MaxC : 256),
(Index : m800x600x16; ModeAX : $006A; ModeBL : $00; MaxC : 16),
(Index : m800x600x256; ModeAX : $0062; ModeBL : $00; MaxC : 256),
(Index : m1024x768x16; ModeAX : $0074; ModeBL : $00; MaxC : 16),
(Index : m1024x768x256; ModeAX : $0063; ModeBL : $00; MaxC : 256));
AcuMOSTable : ModeTable =
((Index : m640x400x256; ModeAX : $0059; ModeBL : $00; MaxC : 256),
(Index : m640x480x256; ModeAX : $005F; ModeBL : $00; MaxC : 256),
(Index : m800x600x16; ModeAX : $0058; ModeBL : $00; MaxC : 16),
(Index : m800x600x256; ModeAX : $005C; ModeBL : $00; MaxC : 256),
(Index : m1024x768x16; ModeAX : $005D; ModeBL : $00; MaxC : 16),
(Index : 0; ModeAX : $0000; ModeBL : $00; MaxC : 0));
GenoaTable : ModeTable =
((Index : m640x400x256; ModeAX : $007E; ModeBL : $00; MaxC : 256),
(Index : m640x480x256; ModeAX : $005C; ModeBL : $00; MaxC : 256),
(Index : m800x600x16; ModeAX : $0079; ModeBL : $00; MaxC : 16),
(Index : m800x600x256; ModeAX : $005E; ModeBL : $00; MaxC : 256),
(Index : m1024x768x16; ModeAX : $005F; ModeBL : $00; MaxC : 16),
(Index : 0; ModeAX : $0000; ModeBL : $00; MaxC : 0));
NCRTable : ModeTable =
((Index : m640x400x256; ModeAX : $005E; ModeBL : $00; MaxC : 256),
(Index : m640x480x256; ModeAX : $005F; ModeBL : $00; MaxC : 256),
(Index : m800x600x16; ModeAX : $0058; ModeBL : $00; MaxC : 16),
(Index : m800x600x256; ModeAX : $005C; ModeBL : $00; MaxC : 256),
(Index : m1024x768x16; ModeAX : $005D; ModeBL : $00; MaxC : 16),
(Index : 0; ModeAX : $0000; ModeBL : $00; MaxC : 0));
OakTable : ModeTable =
((Index : m640x400x256; ModeAX : $0051; ModeBL : $00; MaxC : 256),
(Index : m640x480x256; ModeAX : $0053; ModeBL : $00; MaxC : 256),
(Index : m800x600x16; ModeAX : $0052; ModeBL : $00; MaxC : 16),
(Index : m800x600x256; ModeAX : $0054; ModeBL : $00; MaxC : 256),
(Index : m1024x768x16; ModeAX : $0056; ModeBL : $00; MaxC : 16),
(Index : m1024x768x256; ModeAX : $0058; ModeBL : $00; MaxC : 256));
ATITable : ModeTable =
((Index : m640x400x256; ModeAX : $0061; ModeBL : $00; MaxC : 256),
(Index : m640x480x256; ModeAX : $0062; ModeBL : $00; MaxC : 256),
(Index : m800x600x16; ModeAX : $0054; ModeBL : $00; MaxC : 16),
(Index : m800x600x256; ModeAX : $0063; ModeBL : $00; MaxC : 256),
(Index : m1024x768x16; ModeAX : $0065; ModeBL : $00; MaxC : 16),
(Index : 0; ModeAX : $0000; ModeBL : $00; MaxC : 0));
ChipsTechTable : ModeTable =
((Index : m640x400x256; ModeAX : $0078; ModeBL : $00; MaxC : 256),
(Index : m640x480x256; ModeAX : $0079; ModeBL : $00; MaxC : 256),
(Index : m800x600x16; ModeAX : $0070; ModeBL : $00; MaxC : 16),
(Index : m800x600x256; ModeAX : $007b; ModeBL : $00; MaxC : 256),
(Index : m1024x768x16; ModeAX : $0072; ModeBL : $00; MaxC : 16),
(Index : 0; ModeAX : $0000; ModeBL : $00; MaxC : 0));
ParadiseTable : ModeTable =
((Index : m640x400x256; ModeAX : $005e; ModeBL : $00; MaxC : 256),
(Index : m640x480x256; ModeAX : $005f; ModeBL : $00; MaxC : 256),
(Index : m800x600x16; ModeAX : $0058; ModeBL : $00; MaxC : 16),
(Index : m800x600x256; ModeAX : $005C; ModeBL : $00; MaxC : 256),
(Index : m1024x768x16; ModeAX : $005d; ModeBL : $00; MaxC : 16),
(Index : 0; ModeAX : $0000; ModeBL : $00; MaxC : 0));
EverexTable : ModeTable =
((Index : m640x400x256; ModeAX : $0070; ModeBL : $14; MaxC : 256),
(Index : m640x480x256; ModeAX : $0070; ModeBL : $30; MaxC : 256),
(Index : m800x600x16; ModeAX : $0070; ModeBL : $02; MaxC : 16),
(Index : m800x600x256; ModeAX : $0070; ModeBL : $31; MaxC : 256),
(Index : m1024x768x16; ModeAX : $0070; ModeBL : $20; MaxC : 16),
(Index : m1024x768x256; ModeAX : $0070; ModeBL : $32; MaxC : 256));
Video7Table : ModeTable =
((Index : m640x400x256; ModeAX : $6f05; ModeBL : $66; MaxC : 256),
(Index : m640x480x256; ModeAX : $6f05; ModeBL : $67; MaxC : 256),
(Index : m800x600x16; ModeAX : $6f05; ModeBL : $62; MaxC : 16),
(Index : m800x600x256; ModeAX : $6f05; ModeBL : $69; MaxC : 256),
(Index : m1024x768x16; ModeAX : $6f05; ModeBL : $65; MaxC : 16),
(Index : m1024x768x256; ModeAX : $6f05; ModeBL : $6A; MaxC : 256));
VESATable : ModeTable =
((Index : m640x400x256; ModeAX : $0100; ModeBL : $00; MaxC : 256),
(Index : m640x480x256; ModeAX : $0101; ModeBL : $00; MaxC : 256),
(Index : m800x600x16; ModeAX : $0102; ModeBL : $00; MaxC : 16),
(Index : m800x600x256; ModeAX : $0103; ModeBL : $00; MaxC : 256),
(Index : m1024x768x16; ModeAX : $0104; ModeBL : $00; MaxC : 16),
(Index : m1024x768x256; ModeAX : $0105; ModeBL : $00; MaxC : 256));
var
VESAModeList : Array[0..7] of Word; {table for available VESA modes}
ModeList : ModeTable; {our selected mode table}
VesaVgaInfo : VgaInfoBlockType;
VesaModeInfo : ModeInfoBlockType;
{$ENDIF}
var
SelMode : Byte; {our selected video mode}
{LeftEdge : Integer;} {leftmost pixel of image (0-based)}
{RightEdge : Integer;} {rightmost pixel of image}
TopEdge : Integer; {topmost raster line of image (0-based)}
BotEdge : Integer; {lowest raster line in image}
Raster : Integer; {number of scanlines in selected mode}
Pixels : Integer; {width in pixels of selected mode}
PlotLine : PlotLineProc; {our pointer to PlotLine for mode}
YCord : Word; {the current raster line to plot}
type
{EGA/VGA palette needs}
VGAPalRec =
record
Red,Grn,Blu : Byte;
end;
VGAPalType = Array[0..255] of VGAPalRec; {array of RGB triplets for DAC}
EGAPalType = Array[0..16] of Byte; {include border register}
const
DefEGAPal : EGAPalType = {the default EGA palette}
($00,$01,$02,$03,$04,$05,$14,$07,$38,$39,$3A,$3B,$3C,$3D,$3E,$3F,$00);
var
VGAPalette : VGAPalType;
EGAPalette : EGAPalType;
UniqueCols : Integer;
procedure DoMapping;
{-convert a GIF 24-bit color map to a useable form}
procedure SetDefMap;
{-set a default map when none is in the image}
{$IFDEF UseSVGA}
procedure DetectSVGAType(CheckHW : Boolean);
{-detect whether VESA driver is installed}
{$ENDIF}
procedure AdjustPalette(Mode : Byte);
{-set hardware palette to match image and mode}
procedure SetGraphicsMode(Mode : Byte);
{-select graphics mode}
procedure SetTextMode;
{-restore text mode}
function SelectMode(X,Y : Word) : Byte;
{-select mode to use based on image dimensions}
implementation
var
EGABytesPerLine : Integer; {used by EGA plotting routine}
BankSize : Word;
const
First : Boolean = False;
RetVal : Integer = 0;
BankAdr : Word = 0;
{------------------------}
{ Color mapping services }
{------------------------}
FUNCTION PaletteValue(I : Integer) : Byte;
{-return the 6-bit (EGA) color for the I'th VGA colormap entry}
VAR B, GI : Byte;
begin
with TempMap do begin
GI := $00;
B := Map[I, RedVal];
case B of
$C0..$FF:
GI := GI or $24; {100100b} {high-intensity}
$80..$BF:
GI := GI or $04; {000100b} {low-intensity}
$40..$7F:
GI := GI or $20; {100000b} {medium-intensity}
end;
B := Map[I, GreenVal];
case B of
$C0..$FF:
GI := GI or $12; {010010b}
$80..$BF:
GI := GI or $02; {000010b}
$40..$7F:
GI := GI or $10; {010000b}
end;
B := Map[I, BlueVal];
case B of
$C0..$FF:
GI := GI or $09; {001001b}
$80..$BF:
GI := GI or $01; {000001b}
$40..$7F:
GI := GI or $08; {001000b}
end;
PaletteValue := GI;
end
end;
procedure DoMapping;
{-perform color mapping/conversion}
var
Temp,I,J,K,GI : byte;
EGATemp,Votes : array[0..63] of byte;
procedure SetColorA(I : Integer);
var
N : Integer;
J : Integer;
begin
{find the nearest EGA color for the color number}
GI := PaletteValue(I);
for J := 1 to 4 do begin
{walk thru the palette, looking for a match}
for N := 0 to 15 do
if GI = EGAPalette[n] then begin
{match found, set Color[] and leave}
Color[i] := N;
exit;
end;
{match not found, move to next related color and try again}
GI := (GI + 16) mod 64
end;
{should never get here, but just in case we set the color to the
previous slot's value}
Color[i] := Color[i-1];
end;
procedure ExchangeBytes(var B1, B2 : Byte);
var
B3 : Byte;
begin
B3 := B1;
B1 := B2;
B2 := B3;
end;
begin
EGAPalette := DefEGAPal;
TempMap := Maps[CurMap];
with TempMap do begin
{initialize the VGA palette}
for I := 0 to HighColorNum do begin
VGAPalette[I].Red := Map[I,RedVal] SHR 2;
VGAPalette[I].Grn := Map[I,GreenVal] SHR 2;
VGAPalette[I].Blu := Map[I,BlueVal] SHR 2;
Color[I] := I;
end;
if MaxColors < 256 then begin
if HighColorNum > 15 then begin
{more colors than will fit in the palette; we have to perform
color reduction.}
{init important vars}
for I := 0 to 63 do begin
Votes[i] := 0;
EGATemp[i] := i;
end;
{First find which of the 64 EGA colors is most popular...}
for I := 0 to HighColorNum do begin
GI := PaletteValue(I);
inc(Votes[GI]);
end;
{sort the votes; put the top 16 in the palette}
for I := 0 to 15 do begin
for J := I to 63 do begin
if Votes[j] > Votes[i] then begin
ExchangeBytes(Votes[j], Votes[i]);
ExchangeBytes(EGATemp[j], EGATemp[i]);
end;
end;
end;
{load the palette}
Move(EGATemp, EGAPalette, 16);
{finally, set up Color[] to work with the palette}
for I := 0 to HighColorNum do
SetColorA(I);
end
else begin
{16 colors or less, just set things up equally}
for I := 0 to HighColorNum do begin
EGAPalette[I] := PaletteValue(I);
Color[I] := I;
end;
end;
end;
end;
end;
procedure SetDefMap;
{-assign default map. There is no defined default map in the spec, but}
{ this method matches that used by many decoders.}
var i : byte;
begin
with Maps[CurMap] do
for i := 0 to HighColorNum do
Color[i] := i MOD succ(HighColorNum);
end;
{----------------------}
{ SVGA detect routines }
{----------------------}
{$IFDEF UseSVGA}
procedure AdjustVESATable;
{-adjusts the VESA modestable to reflect actual VESA modes supported}
var
W : Word;
B : Array[0..5] of Boolean;
begin
FillChar(B,SizeOf(B),0);
with VesaVgaInfo do begin
{walk thru modeslist looking for VESA entry types ($100..$105)}
W := 0;
while (W < 100) and
{$IFDEF Dpmi}
(VideoModePtr <> nil) and
{$ENDIF}
(VideoModePtr^[W] <> $FFFF) do begin
if (VideoModePtr^[W] >= $100) and (VideoModePtr^[W] < $106) then
B[VideoModePtr^[W] - $100] := True;
Inc(W);
end;
{now walk thru boolean array setting table to match}
for W := 0 to 5 do
if NOT(B[w]) then
ModeList[w+1].Index := 0;
end;
end;
procedure Cirrus; near; Assembler;
asm
mov dx,3d4h
mov al,0ch
out dx,al
inc dx
mov ah,al
in al,dx
xchg ah,al
push ax
push dx
xor al,al
out dx,al
mov al,1fh
dec dx
out dx,al
inc dx
in al,dx
mov bh,al
mov cl,4
mov dx,3c4h
mov bl,6
ror bh,cl
mov ax,bx
out dx,ax
inc dx
in al,dx
or al,al
jnz @@exit
ror bh,cl
dec dx
mov ax,bx
out dx,ax
inc dx
in al,dx
cmp al,1
jne @@exit
mov [svgatype],vtCirrus
@@exit:
pop dx
dec dx
pop ax
out dx,ax
end;
procedure NewBank; far; Assembler;
asm
push cx
mov cx,[svgatype]
cmp cx,vtVESA
je @@_vesa
cmp cx,vtTseng4000
je @@_tseng4
cmp cx,vtTseng3000
je @@_tseng
cmp cx,vtTrident8800
je @@_trident
cmp cx,vtTrident8900
je @@_trident
cmp cx,vtS3Vga
je @@_s3vga
cmp cx,vtATIVGA
je @@_ativga
cmp cx,vtacumos
je @@_acumos
cmp cx,vtParadise
je @@_paradise
cmp cx,vtVideo7
je @@_video7
cmp cx,vtCompaq
je @@_compaq
cmp cx,vtGenoa
je @@_genoa
cmp cx,vtChipsTech
je @@_chipstech
cmp cx,vtAheadA
je @@_aheada
cmp cx,vtAheadB
je @@_aheadb
cmp cx,vtNCR
je @@_ncr
cmp cx,vtEverex
je @@_everex
cmp cx,vtOakTech
je @@_oaktech
jmp @@_nobank
@@_tseng:
push ax
push dx
cli
mov [curbk],ax
and al,7
mov ah,al
shl al,1
shl al,1
shl al,1
or al,ah
or al,01000000b
mov dx,3cdh
out dx,al
sti
pop dx
pop ax
jmp @@alldone
@@_tseng4:
push ax
push dx
cli
mov [curbk],ax
mov ah,al
mov dx,3bfh
mov al,3
out dx,al
mov dl,0d8h
mov al,0a0h
out dx,al
and ah,15
mov al,ah
shl al,1
shl al,1
shl al,1
shl al,1
or al,ah
mov dl,0cdh
out dx,al
sti
pop dx
pop ax
jmp @@alldone
@@_trident:
push ax
push dx
push ax
cli
mov [curbk],ax
mov dx,3ceh
mov al,6
out dx,al
inc dl
in al,dx
dec dl
or al,4
mov ah,al
mov al,6
out dx,ax
mov dl,0c4h
mov al,0bh
out dx,al
inc dl
in al,dx
dec dl
pop ax
mov ah,al
xor ah,2
mov dx,3c4h
mov al,0eh
out dx,ax
sti
pop dx
pop ax
jmp @@alldone
@@_video7:
push ax
push dx
push cx
cli
mov [curbk],ax
and ax,15
mov ch,al
mov dx,3c4h
mov ax,0ea06h
out dx,ax
mov ah,ch
and ah,1
mov al,0f9h
out dx,ax
mov al,ch
and al,1100b
mov ah,al
shr ah,1
shr ah,1
or ah,al
mov al,0f6h
out dx,al
inc dx
in al,dx
dec dx
and al,not 1111b
or ah,al
mov al,0f6h
out dx,ax
mov ah,ch
mov cl,4
shl ah,cl
and ah,100000b
mov dl,0cch
in al,dx
mov dl,0c2h
and al,not 100000b
or al,ah
out dx,al
sti
pop cx
pop dx
pop ax
jmp @@alldone
@@_paradise:
push ax
push dx
push ax
cli
mov [curbk],ax
mov dx,3ceh
mov ax,50fh
out dx,ax
pop ax
mov ah,al
mov al,9
out dx,ax
sti
pop dx
pop ax
jmp @@alldone
@@_acumos:
push ax
push dx
push ax
cli
mov [curbk],ax
mov dx,3c4h
mov ax,1206h
out dx,ax
mov dx,3ceh
pop ax
mov ah,al
mov al,9
out dx,ax
sti
pop dx
pop ax
jmp @@alldone
@@_chipstech:
push ax
push dx
push ax
cli
mov [curbk],ax
mov dx,46e8h
mov ax,1eh
out dx,ax
mov dx,103h
mov ax,0080h
out dx,ax
mov dx,46e8h
mov ax,0eh
out dx,ax
pop ax
mov ah,al
mov al,10h
mov dx,3d6h
out dx,ax
sti
pop dx
pop ax
jmp @@alldone
@@_ativga:
push ax
push dx
cli
mov [curbk],ax
mov ah,al
mov dx,1ceh
mov al,0b2h
out dx,al
inc dl
in al,dx
shl ah,1
and al,0e1h
or ah,al
mov al,0b2h
dec dl
out dx,ax
sti
pop dx
pop ax
jmp @@alldone
@@_everex:
push ax
push dx
push cx
cli
mov [curbk],ax
mov cl,al
mov dx,3c4h
mov al,8
out dx,al
inc dl
in al,dx
dec dl
shl al,1
shr cl,1
rcr al,1
mov ah,al
mov al,8
out dx,ax
mov dl,0cch
in al,dx
mov dl,0c2h
and al,0dfh
shr cl,1
jc @@nob2
or al,20h
@@nob2:
out dx,al
sti
pop cx
pop dx
pop ax
jmp @@alldone
@@_aheada:
push ax
push dx
push cx
cli
mov [curbk],ax
mov ch,al
mov dx,3ceh
mov ax,200fh
out dx,ax
mov dl,0cch
in al,dx
mov dl,0c2h
and al,11011111b
shr ch,1
jnc @@skpa
or al,00100000b
@@skpa:
out dx,al
mov dl,0cfh
mov al,0
out dx,al
inc dx
in al,dx
dec dx
and al,11111000b
or al,ch
mov ah,al
mov al,0
out dx,ax
sti
pop cx
pop dx
pop ax
jmp @@alldone
@@_aheadb:
push ax
push dx
push cx
cli
mov [curbk],ax
mov ch,al
mov dx,3ceh
mov ax,200fh
out dx,ax
mov ah,ch
mov cl,4
shl ah,cl
or ah,ch
mov al,0dh
out dx,ax
sti
pop cx
pop dx
pop ax
jmp @@alldone
@@_oaktech:
push ax
push dx
cli
mov [curbk],ax
and al,15
mov ah,al
shl al,1
shl al,1
shl al,1
shl al,1
or ah,al
mov al,11h
mov dx,3deh
out dx,ax
sti
pop dx
pop ax
jmp @@alldone
@@_genoa:
push ax
push dx
cli
mov [curbk],ax
mov ah,al
shl al,1
shl al,1
shl al,1
or ah,al
mov al,6
or ah,40h
mov dx,3c4h
out dx,ax
sti
pop dx
pop ax
jmp @@alldone
@@_ncr:
push ax
push dx
cli
mov [curbk],ax
mov ah,al
mov al,18h
mov dx,3c4h
out dx,ax
mov ax,19h
out dx,ax
sti
pop dx
pop ax
jmp @@alldone
@@_compaq:
push ax
push dx
push ax
cli
mov [curbk],ax
mov dx,3ceh
mov ax,50fh
out dx,ax
pop ax
mov ah,al
mov al,45h
out dx,ax
sti
pop dx
pop ax
jmp @@alldone
@@_s3vga:
push ax
push dx
cli
mov [curbk],ax
sti
pop dx
pop ax
jmp @@alldone
@@_vesa:
push ax
cli
mov [curbk],ax
mov dx,ax
xor bx,bx
mov ax,4f05h
push bp
int 10h
pop bp
sti
pop ax
jmp @@alldone
@@_nobank:
cli
mov [curbk],ax
sti
@@alldone:
pop cx
end;
procedure GoChk; near; Assembler;
asm
push si
mov si,bx
mov al,cl
call NewBank
xchg bl,es:[di]
mov al,ch
call NewBank
xchg bh,es:[di]
xchg si,bx
mov al,cl
call NewBank
xor bl,es:[di]
mov al,ch
call NewBank
xor bh,es:[di]
xchg si,bx
mov al,ch
call NewBank
mov es:[di],bh
mov al,cl
call NewBank
mov es:[di],bl
mov al,0
call NewBank
or si,si
pop si
end;
procedure ChkBk; near; Assembler;
asm
mov di,[SegB800]
mov es,di
xor di,di
mov bx,1234h
call gochk
jnz @@badchk
mov bx,4321h
call gochk
jnz @@badchk
clc
jmp @@goodchk
@@badchk:
stc
@@goodchk:
end;
procedure IsPort2; near; Assembler;
asm
push bx
mov bx,ax
out dx,al
mov ah,al
inc dx
in al,dx
dec dx
xchg al,ah
push ax
mov ax,bx
out dx,ax
out dx,al
mov ah,al
inc dx
in al,dx
dec dx
and al,bh
cmp al,bh
jnz @@noport
mov al,ah
mov ah,0
out dx,ax
out dx,al
mov ah,al
inc dx
in al,dx
dec dx
and al,bh
cmp al,0
@@noport:
pop ax
out dx,ax
pop bx
end;
procedure IsPort1; near; Assembler;
asm
mov ah,al
in al,dx
push ax
mov al,ah
out dx,al
in al,dx
and al,ah
cmp al,ah
jnz @@noport
mov al,0
out dx,al
in al,dx
and al,ah
cmp al,0
@@noport:
pop ax
out dx,al
end;
procedure WhichVGA; Assembler;
asm
push bp
push ax
push bx
push cx
push dx
push di
push si
push es
cmp [first],1
jb @@gotest
mov ax,[retval]
mov [svgatype],ax
jmp @@skipout
@@gotest:
mov [first],1
mov [vgamem],256
mov [bksize],64
mov [vesaavail],0
xor ax,ax
mov [svgatype],ax
mov ax,ds
mov es,ax
lea di,VESAVgaInfo
mov ax,4f00h
push bp
int 10h
pop bp
cmp ax,4fh
jnz @@novesa
mov [svgatype],vtVESA
mov [vesaavail],1
mov [bksize],64
@@novesa:
mov ax,[VidBIOSSele]
mov es,ax
cmp word ptr es:[40h],'13'
jnz @@noati
mov [svgatype],vtATIVGA
mov [bksize],64
mov dx,es:[10h]
mov bl,es:[43h]
cmp bl,'3'
jae @@v6up
mov al,0bbh
cli
out dx,al
inc dx
in al,dx
sti
test al,20h
jz @@no512
mov [vgamem],512
jmp @@no512
@@v6up:
mov al,0b0h
cli
out dx,al
inc dx
in al,dx
sti
test al,10h
jz @@v7up
mov [vgamem],512
@@v7up:
cmp bl,'4'
jb @@no512
test al,8
jz @@no512
mov [vgamem],1024
@@no512:
jmp @@fini
@@noati:
mov ax,7000h
xor bx,bx
cld
push bp
int 10h
pop bp
cmp al,70h
jnz @@noev
mov [svgatype],vtEverex
mov [bksize],64
and ch,11000000b
jz @@skp
mov [vgamem],512
@@skp:
@@noev:
mov ax,0bf03h
xor bx,bx
mov cx,bx
push bp
int 10h
pop bp
cmp ax,0bf03h
jnz @@nocp
test cl,40h
jz @@nocp
mov [svgatype],vtCompaq
mov [bksize],4
mov [vgamem],512
jmp @@fini
@@nocp:
mov dx,3c4h
mov ax,0ff05h
call isport2
jnz @@noncr
mov ax,5
out dx,ax
mov ax,0ff10h
call isport2
jz @@noncr
mov ax,105h
out dx,ax
mov ax,0ff10h
call isport2
jnz @@noncr
mov [svgatype],vtNCR
mov [bksize],16
mov [vgamem],512
jmp @@fini
@@noncr:
mov dx,3c4h
mov al,0bh
out dx,al
inc dl
in al,dx
and al,0fh
cmp al,06h
ja @@notri
cmp al,2
jb @@notri
mov [svgatype],vtTrident8800
mov [bksize],64
cmp al,3
jb @@no89
mov [svgatype],vtTrident8900
mov dx,3d5h
mov al,1fh
out dx,al
inc dx
in al,dx
and al,3
cmp al,1
jb @@notmem
mov [vgamem],512
je @@notmem
mov [vgamem],1024
@@notmem:
jmp @@fini
@@no89:
mov [vgamem],512
jmp @@fini
@@notri:
mov ax,6f00h
xor bx,bx
cld
push bp
int 10h
pop bp
cmp bx,'V7'
jnz @@nov7
mov [svgatype],vtVideo7
mov [bksize],64
mov ax,6f07h
cld
push bp
int 10h
pop bp
and ah,7fh
cmp ah,1
jbe @@skp2
mov [vgamem],512
@@skp2:
cmp ah,3
jbe @@skp3
mov [vgamem],1024
@@skp3:
jmp @@fini
@@nov7:
mov dx,3d4h
mov ax,032eh
call isport2
jnz @@nogn
mov dx,3c4h
mov ax,3f06h
call isport2
jnz @@nogn
mov [svgatype],vtGenoa
mov [bksize],64
mov [vgamem],512
jmp @@fini
@@nogn:
call cirrus
cmp [svgatype],vtCirrus
jne @@noci
jmp @@fini
@@noci:
mov dx,3ceh
mov al,9
out dx,al
inc dx
in al,dx
dec dx
or al,al
jnz @@nopd
mov ax,50fh
out dx,ax
mov [svgatype],vtParadise
mov cx,1
call chkbk
mov [svgatype],0
jc @@nopd
mov [svgatype],vtParadise
mov [bksize],4
mov dx,3ceh
mov al,0bh
out dx,al
inc dx
in al,dx
test al,80h
jz @@nop512
mov [vgamem],512
@@nop512:
jmp @@fini
@@nopd:
mov ax,5f00h
xor bx,bx
cld
push bp
int 10h
pop bp
cmp al,5fh
jnz @@noct
mov [svgatype],vtChipsTech
mov [bksize],16
cmp bh,1
jb @@skp4
mov [vgamem],512
@@skp4:
jmp @@fini
@@noct:
mov ch,0
mov dx,3d4h
mov ax,0f33h
call isport2
jnz @@not4
mov ch,1
mov dx,3bfh
mov al,3
out dx,al
mov dx,3d8h
mov al,0a0h
out dx,al
jmp @@yes4
@@not4:
mov dx,3d4h
mov ax,1f25h
call isport2
jnz @@nots
mov al,03fh
jmp @@yes3
@@yes4:
mov al,0ffh
@@yes3:
mov dx,3cdh
call isport1
jnz @@nots
mov [svgatype],vtTseng3000
mov [bksize],64
cmp ch,0
jnz @@t4mem
mov [vgamem],512
jmp @@fini
@@t4mem:
mov dx,3d4h
mov al,37h
out dx,al
inc dx
in al,dx
test al,1000b
jz @@nomem
and al,3
cmp al,1
jbe @@nomem
mov [vgamem],512
cmp al,2
je @@nomem
mov [vgamem],1024
@@nomem:
mov [svgatype],vtTseng4000
mov [bksize],64
jmp @@fini
@@nots:
mov dx,3ceh
mov ax,200fh
out dx,ax
inc dx
in al,dx
cmp al,21h
jz @@verb
cmp al,20h
jnz @@noab
mov [svgatype],vtAheadA
mov [bksize],64
mov [vgamem],512
jmp @@fini
@@verb:
mov [svgatype],vtAheadB
mov [bksize],64
mov [vgamem],512
jmp @@fini
@@noab:
mov dx,3c4h
mov ax,0006h
out dx,ax
mov ax,0ff09h
call isport2
jz @@noacu
mov ax,0ff0ah
call isport2
jz @@noacu
mov ax,1206h
out dx,ax
mov ax,0ff09h
call isport2
jnz @@noacu
mov ax,0ff0ah
call isport2
jnz @@noacu
mov [svgatype],vtAcuMOS
mov cx,1
call chkbk
mov [svgatype],0
jc @@noacu
mov [svgatype],vtAcuMOS
mov [bksize],4
mov dx,3c4h
mov al,0ah
out dx,al
inc dx
in al,dx
and al,3
cmp al,1
jb @@noamem
mov [vgamem],512
cmp al,2
jb @@noamem
mov [vgamem],1024
cmp al,3
jb @@noamem
mov [vgamem],2048
@@noamem:
jmp @@fini
@@noacu:
mov dx,3deh
mov ax,0ff11h
call isport2
jnz @@nooak
mov [svgatype],vtOakTech
mov [bksize],64
mov al,0dh
out dx,al
inc dx
in al,dx
test al,11000000b
jz @@no4ram
mov [vgamem],512
test al,01000000b
jz @@no4ram
mov [vgamem],1024
@@no4ram:
jmp @@fini
@@nooak:
jmp @@nos3
mov [svgatype],vtS3Vga
mov [bksize],64
mov [vgamem],1024
jmp @@fini
@@nos3:
cmp [vesaavail],0
je @@nosvga
mov [vgamem],2048
jmp @@fini
@@nosvga:
mov [svgatype],0
@@fini:
cmp [vesaavail],1
jne @@sorry
mov [svgatype],vtVESA
@@sorry:
mov ax,[svgatype]
mov [retval],ax
@@skipout:
pop es
pop si
pop di
pop dx
pop cx
pop bx
pop ax
pop bp
end;
procedure DetectSVGAType(CheckHW : Boolean);
var
Reg : Registers;
Tmp : Integer;
begin
if CurrentDisplay <> VGA then exit;
if (CheckHW) or (not(VidChecked)) then begin
VidChecked := True;
WhichVGA;
BankSize := Word((LongInt(BkSize) * 1024)-1);
end;
end;
{$ENDIF}
{-------------------------}
{ Video hardware routines }
{-------------------------}
procedure PlotBIOSPixel(X,Y : Word; C : Byte);
{-plot a single pixel using BIOS services}
var
R : Registers;
begin
asm
mov ah,0Ch
mov al,C
mov cx,X
mov dx,Y
push bp
int 10h
pop bp
end;
end;
procedure PlotBIOSLine(Y : Word);
{-plot a raster line using BIOS services}
var
X : Integer;
begin
asm
xor bx,bx
mov si,offset RasterLine
mov dx,Y
mov ah,0Ch
xor al,al
mov cx,RightEdge
sub cx,LeftEdge
cld
@@Top:
jcxz @@Done
mov al,[si+bx]
push ax
push bx
push cx
mov cx,bx
add cx,LeftEdge
xor bx,bx
push bp
int 10h
pop bp
pop cx
pop bx
pop ax
inc bx
loop @@Top
@@Done:
end;
end;
procedure PlotCGALoLine(Y : Word);
{-plot a raster line in CGA 320x200x4 mode}
var
X,M,VOfs : Word;
Tmp : Array[0..79] of Byte;
begin
{calc offset in vmem of scanline to plot}
VOfs := ((Y and 1) shl 13) + (80 * (Y shr 1)) + ((LeftEdge shr 2) mod 80);
M := 0;
FillChar(Tmp,80,0);
X := LeftEdge;
{load our holding buffer with the line. CGA low uses 2 bits/pixel}
repeat
Tmp[m] := Tmp[m] or (((RasterLine[X] and $03) shl 6) shr ((X mod 4) shl 1));
Inc(X);
if (X and 3) = 0 then Inc(M);
until X > RightEdge;
{move the line to vmem}
Move(Tmp,Ptr(ColorSele,VOfs)^,M);
end;
procedure PlotCGAHiLine(Y : Word);
{-plot a raster line in CGA 640x200x2 mode}
var
X,M,VOfs : Word;
Tmp : Array[0..79] of Byte;
begin
{same as CGALo, but uses 1 bit/pixel}
VOfs := ((Y and 1) shl 13) + (80 * (Y shr 1)) + ((LeftEdge shr 3) mod 80);
M := 0;
FillChar(Tmp,80,0);
X := LeftEdge;
repeat
Tmp[m] := Tmp[m] or (((RasterLine[X] and 1) shl 7) shr (X mod 8));
Inc(X);
if (X and 7) = 0 then Inc(M);
until X > RightEdge;
Move(Tmp,Ptr(ColorSele,VOfs)^,M);
end;
procedure PlotEGALine(Y : Word);
{-plot EGA raster line in modes $0D - $12}
var
I : Word;
begin
asm
mov ax,Y
mul EGABytesPerLine
mov bx,LeftEdge
shr bx,1
shr bx,1
shr bx,1
add ax,bx
mov di,ax
mov es,VGASele
mov si,offset RasterLine
mov ah,80h
mov cx,LeftEdge
ror ah,cl
mov dx,3CEh
mov cx,RightEdge
sub cx,LeftEdge
inc cx
mov al,08h
cld
@@Top:
jcxz @@Done
out dx,ax
mov bl,[si]
mov bh,es:[di]
mov es:[di],bl
inc si
ror ah,1
cmp ah,80h
jne @@Check
inc di
@@Check:
loop @@Top
@@Done:
end;
end;
procedure PlotEGALineDbl(Y : Word);
{-plot special EGA raster line in mode $12 for expanded weather maps}
begin
Move(RasterLine[0], RasterLine[1280], 378);
asm
mov si,offset RasterLine
mov di,si
add si,1280
mov ax,ds
mov es,ax
mov cx,378
xor bx,bx
cld
@@Top:
jcxz @@Done
movsb
dec si
movsb
inc bx
cmp bx,5
jne @@Skip
xor bx,bx
dec cx
inc si
@@Skip:
loop @@Top
@@Done:
end;
PlotEGALine(Y);
PlotEGALine(Y+1);
end;
procedure PlotVGALine(Y : Word);
{-plot a raster line in VGA mode $13}
begin
asm
mov ax,Y
mul Pixels
add ax,LeftEdge
mov di,ax
mov es,VGASele
mov si,offset RasterLine
mov cx,RightEdge
sub cx,LeftEdge
cld
rep movsb
end;
end;
{$IFDEF UseSVGA}
procedure PlotSVGALine(Y : Word);
{-plot a raster line in SVGA modes}
begin
asm
mov ax,Y
cwd
mul Pixels
add ax,LeftEdge
adc dx,0
push ax
cmp dx,CurBk
jne @@Switch1
mov cx,RightEdge
sub cx,LeftEdge
add ax,cx
adc dx,0
cmp dx,CurBk
jne @@Switch2
@@NoSwitch:
mov si,offset RasterLine
mov es,VGASele
pop di
cld
rep movsb
jmp @@Done
@@Switch1:
mov CurBk,dx
xor dx,dx
mov ax,CurBk
call NewBank
jmp @@Skip
@@Switch2:
mov CurBk,dx
xor dx,dx
@@Skip:
mov cx,RightEdge
sub cx,LeftEdge
pop di
mov si,offset RasterLine
mov es,VGASele
cld
@@Top:
jcxz @@Done
movsb
cmp di,0
ja @@SkipSwitch
mov ax,CurBk
call NewBank
@@SkipSwitch:
loop @@Top
@@Done:
end;
end;
{$ENDIF}
{---------------------------------------------------------------------------}
procedure AdjustPalette(Mode : Byte);
{-set hardware palette to match image map}
var R : Registers;
begin
FillChar(RasterLine,SizeOf(TRasterLine),0); {blank line to start}
with R do begin
if Mode >= $13 then begin
ah := $10;
al := $12;
bx := 0;
cx := Maps[Curmap].HighColorNum+1; {# of palette entries in use}
es := Seg(VGAPalette);
dx := Ofs(VGAPalette);
Intr($10, R);
end
else if Mode >= $0D then begin
ah := $10;
al := $02;
bx := 0;
es := Seg(EGAPalette);
dx := Ofs(EGAPalette);
Intr($10, R);
end;
end;
end;
procedure SetMode(Mode : Byte);
{-low level video mode set via BIOS}
var R : Registers;
begin
R.ah := $00;
R.al := Mode;
Intr($10,R);
end;
{$IFDEF UseSVGA}
procedure SetSVGAMode(Mode : Byte);
{-special BIOS setmode for SVGA chipsets, using ModeList. Some SVGA}
{chipsets use a constant AX value for SVGA modes with a second value}
{in BL to select the actual mode; we handle that here. }
var
B : Integer;
R : Registers;
begin
B := Mode - $F0;
MaxColors := ModeList[B].MaxC;
if SVGAType = vtVESA then begin
R.ax := $4F02;
R.bx := ModeList[B].ModeAX;
end
else begin
R.ax := ModeList[B].ModeAX;
R.bl := ModeList[B].ModeBL;
end;
Intr($10,R);
if SVGAType = vtVESA then begin
R.ax := $4F01;
R.cx := ModeList[B].ModeAX;
R.es := Seg(VesaModeInfo);
R.di := Ofs(VesaModeInfo);
Intr($10,R);
end;
end;
procedure SelectModeTable;
{-select which modetable to use based on chipset type}
begin
FillChar(ModeList,SizeOf(ModeList),0);
case SVGAType of
vtTseng3000:
ModeList := Tseng3000Table;
vtTseng4000:
ModeList := Tseng4000Table;
vtTrident8800:
ModeList := TridentTable;
vtTrident8900:
ModeList := Trident8900Table;
vtParadise:
ModeList := ParadiseTable;
vtVideo7:
ModeList := Video7Table;
vtATIVGA:
ModeList := ATITable;
vtChipsTech:
ModeList := ChipsTechTable;
vtAheadA, vtAheadB:
ModeList := AheadTable;
vtEverex:
ModeList := EverexTable;
vtAcuMOS:
ModeList := AcuMOSTable;
vtNCR:
ModeList := NCRTable;
vtGenoa:
ModeList := GenoaTable;
vtOakTech:
ModeList := OakTable;
vtVESA:
ModeList := VESATable;
end;
end;
{$ENDIF}
procedure SetGraphicsMode(Mode : Byte);
{-sets selected grahics mode}
begin
OldMode := LastMode;
OldFont8x8 := Font8x8Selected;
{$IFDEF UseSVGA}
if (Mode > $13) and (SVGAType > 0) then
SetSVGAMode(Mode)
else
{$ENDIF}
if Mode = $09 then begin
if WhichHerc = HercInColor then
SwitchInColorCard(False);
SetHercMode(True,0);
{clear the screen}
FillChar(Ptr(SegB000, 0)^,$7FFF,0);
end
else
SetMode(Mode); {low-level video mode set}
if (Mode >= $0D) and (Mode <= $12) then begin
{EGA, set up EGA CRTC as we need it}
PortW[$03CE] := $1803;
PortW[$03CE] := $0205;
end;
GraphOn := True;
end;
procedure SetTextMode;
{-restore text mode}
begin
if SelMode = $09 then begin
SetHercMode(False,0);
if WhichHerc = HercInColor then
SwitchInColorCard(True);
end
else
SetMode(OldMode);
TextMode(OldMode);
SelectFont8x8(OldFont8x8);
ReinitCrt;
ClrScr;
GraphOn := False;
end;
procedure FillBackground;
var
W : Word;
begin
LeftEdge := 0;
RightEdge := ScrWidth;
FillChar(RasterLine, SizeOf(RasterLine), Maps[Global].BackgrColorIndex);
for W := 0 to Pred(ScrHeight) do
PlotLine(W);
FillChar(RasterLine, SizeOf(RasterLine), 0);
end;
function SelectMode(X,Y : Word) : Byte;
{-uses image X/Y resolution to select video mode}
var
B : Byte;
begin
DetectSVGAType(True);
EGABytesPerLine := 80;
MaxColors := 16;
Pixels := 640;
PlotLine := PlotEGALine;
if (CurrentDisplay in [EGA,VGA]) and
(X = 378) and
(Y = 240) then begin
{CIS Weather map in odd size, do special handling}
if (DoDbl) then begin
Pixels := 378*2;
Raster := 480;
MaxColors := 16;
SelectMode := $12;
PlotLine := PlotEGALineDbl;
end
else begin
Pixels := 640;
Raster := 480;
MaxColors := 16;
SelectMode := $12;
PlotLine := PlotEGALine;
end;
exit;
end;
{$IFDEF UseSVGA}
{if we're an SVGA, select a matching mode}
if (CurrentDisplay = VGA) and (SVGAType > 0) then begin
{set our mode table and vars}
SelectModeTable;
PlotLine := PlotSVGALine;
MaxColors := 256;
CurBk := 0;
{Match a mode index to Y res. The vast majority of SVGA GIFs are}
{"tall/narrow" rather than "short/wide", so this is a safe match,}
{but we allow for 640x200 CGA-type images as well.}
case Y of
601..MaxInt:
B := $F6;
481..600:
B := $F4;
401..480:
B := $F2;
201..400:
B := $F1;
else
begin
if X > 320 then
B := $F1
else begin
SelectMode := $13;
Raster := 200;
Pixels := 320;
PlotLine := PlotVGALine;
exit;
end;
end;
end;
{walk up mode table til we get a supported mode}
while (B > $F1) and (ModeList[B-$F0].Index = 0) do
Dec(B);
{now match colors and resolution}
SelectMode := B;
MaxColors := ModeList[B-$F0].MaxC;
case B of
$F5,$F6:
begin
Raster := 768;
Pixels := 1024;
end;
$F3,$F4:
begin
Raster := 600;
Pixels := 800;
end;
$F2:
begin
Raster := 480;
Pixels := 640;
end;
$F1:
begin
Raster := 400;
Pixels := 640;
end;
end;
{16 color modes > 640x480 are wierd, use the BIOS to plot}
if (MaxColors = 16) and (Raster > 480) then
PlotLine := PlotBIOSLine;
end
else
{$ENDIF}
if (CurrentDisplay = EGA) or (CurrentDisplay = VGA) then begin
{if > 350 lines, use EGA/VGA mode $12 (640x480x16)}
EGABytesPerLine := 80;
MaxColors := 16;
Pixels := 640;
PlotLine := PlotEGALine;
if (Y > 350) and ((CurrentDisplay = VGA) or (AllowEGAMode12)) then begin
Raster := 480;
SelectMode := $12;
end
{if we fit CGAHi specs, use it}
else if (Y <= 200) and (X <= 640) and
(Maps[CurMap].HighColorNum < 2) then begin
Raster := 200;
Pixels := 640;
PlotLine := PlotCGAHiLine;
SelectMode := $06;
end
else if (Y <= 200) and (X <= 320) then begin
{if we meet std. VGA specs, use VGA mode $13 (320x200x256)}
if (CurrentDisplay = VGA) then begin
MaxColors := 256;
Raster := 200;
Pixels := 320;
PlotLine := PlotVGALine;
SelectMode := $13;
end
{otherwise use EGA native mode $0D (320x200x16)}
else begin
Raster := 200;
Pixels := 320;
EGABytesPerLine := 40;
SelectMode := $0D;
end;
end
{default to "standard" EGA/VGA mode $10 (640x350x16)}
else begin
Raster := 350;
SelectMode := $10;
end;
end
else if CurrentDisplay = CGA then begin
{if > 320 pixels, use CGA mode $06}
Raster := 200;
if X > 320 then begin
PlotLine := PlotCGAHiLine;
Pixels := 640;
SelectMode := $06;
end
else begin
{use CGA mode $05, which turns off color burst to "grayscale" image}
{since the standard CGA palettes match almost nothing <g>}
PlotLine := PlotCGALoLine;
Pixels := 320;
SelectMode := $05;
end;
end
else begin
WriteLn('** Unsupported video system detected **');
SelectMode := 0;
end;
end;
{$IFDEF Dpmi}
begin
GetSelectorForRealMem(Ptr($A000,0), $FFFF, VGASele);
GetSelectorForRealMem(Ptr($C000,0), $FFFF, VidBIOSSele);
{$ENDIF}
end.